package com.redisson.controller;

import com.redisson.service.RedisService;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @作者: 林江
 * @创建时间: 2024/2/10
 * @功能:
 */
@RestController
@RequestMapping("redis")
public class RedisController {

    @Autowired
    RedisService redisService;
    @Autowired
    RedissonClient redisson;
    @Resource
    private RedisTemplate redis;

    @GetMapping("listTree")
    public String listTree() {
        return redisService.listCategoryTree();
    }

    /*-------------------------------读写锁-----------------------------*/
    @GetMapping("write")
    public String write() {
        RReadWriteLock readWriteLock = redisson.getReadWriteLock("read-write-lock");
        RLock writeLock = readWriteLock.writeLock();
        try {
            writeLock.lock();

            try {
                TimeUnit.SECONDS.sleep(10);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

        } finally {
            writeLock.unlock();
        }
        return "测试redisson的读写锁 -- 写锁";
    }

    @GetMapping("read")
    public String read() {
        RReadWriteLock readWriteLock = redisson.getReadWriteLock("read-write-lock");
        RLock rLock = readWriteLock.readLock();
        try {
            rLock.lock();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } finally {
            rLock.unlock();
        }

        return "测试redisson的读写锁 -- 写锁";
    }

    /*-------------------------------信号量-----------------------------*/
    // 模拟10个停车位
    @GetMapping("enter")
    public String enter() throws InterruptedException {
        RSemaphore semaphore = redisson.getSemaphore("park");
//        semaphore.acquire();  // 如果没有停车许可证，所有的车辆就会阻塞等待。
        boolean acquire = semaphore.tryAcquire(); // 尝试去获取许可证，没有获取到，无需等待，立马调转。
        if (!acquire) {
            return "没有车位了。。。。。";
        }
        return "占用一个停车位";
    }

    @GetMapping("go")
    public String go() throws InterruptedException {
        RSemaphore semaphore = redisson.getSemaphore("park");
        // 释放的时候，停车位全部空了，就不能在释放了。
        semaphore.release();
        return "空了一个停车位";
    }

    @GetMapping("init")
    public String init() throws InterruptedException {
        int park = 10;
        RSemaphore semaphore = redisson.getSemaphore("park");
        semaphore.trySetPermits(park);
        return "新建了" + park + "个停车位。";
    }


    @GetMapping("enterExpire")
    public String enterExpire() throws InterruptedException {
        RPermitExpirableSemaphore expirableSemaphore = redisson.getPermitExpirableSemaphore("park");
        expirableSemaphore.trySetPermits(1);
        // 这个许可证3s内有效
        String id = expirableSemaphore.acquire(3, TimeUnit.SECONDS);

        // 尝试获取3s内的许可证。
        String acquire = expirableSemaphore.tryAcquire(1, 3, TimeUnit.SECONDS);
        while (acquire == null) {
            System.out.println("循环次数");
            acquire = expirableSemaphore.tryAcquire(1, 3, TimeUnit.SECONDS);
        }
        return "许可证的租赁时间:" + acquire;
    }

    /*----------------------------------CountDownLatch---------------------------------------*/
    @GetMapping("await")
    public String await() throws InterruptedException {
        RCountDownLatch countDownLatch = redisson.getCountDownLatch("latch");
        countDownLatch.trySetCount(10);

        countDownLatch.await(); // 一直阻塞。。。
        return "全部完成。。。。";
    }

    @GetMapping("countDown")
    public String countDown() throws InterruptedException {
        RCountDownLatch countDownLatch = redisson.getCountDownLatch("latch");
        countDownLatch.countDown(); // 减一
        return "完成了一个";
    }

}
